require "#{RAILS_ROOT}/app/classes/cat/rules/rule"

#* stopping_rule.rb
#* Copyright (C) 2010  Embian Inc.
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or 
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with This program.  If not, see <http://www.gnu.org/licenses/>.
#  
#* Defines "Stopping Rule" for CAT
#* Author: KyoungMo Yang(E-mail : mo@embian.com)
#* Modified: 2010-11-30
#* References: Rule
module StoppingRule
  include Rule
  
  #* Functionailities
  # * Implements Rule#run
  #* Parameters 
  # * [*args] : argement list
  #* Return
  # * N/A
  #* Note
  # * Override Rule#run
  def run(*args)
    if maximum_criterion
      return true
    end
    return satisfy_criterion
  end
  
  private
  #* Functionailities
  # * Implements "SEM Rule" as Stopping Rule of CAT
  #   Formula : SE(Θ) = 1 / sqrt(I(Θ))
  #             I(Θ) = 1 / a^2*P(Θ)Q(Θ)
  #             P(Θ) = c + (1-c) * (1 / (1 + exp(-1.7*a*(Θ-b))))
  #* Parameters 
  # * N/A
  #* Return
  # * [result] : Returns true if satisfy SEM Stopping Rule
  #* Note
  # * N/A
  def satisfy_criterion
    cat_item = profile.exam.last_item
    return false unless cat_item
    
    prev_i = cat_item.I_of(profile.prev_theta, profile.cat_model)
    prev_se = 1.0 / Math.sqrt(prev_i)
    
    i = cat_item.I_of(profile.theta, profile.cat_model)
    se = 1.0 / Math.sqrt(i)
    
    if (prev_se - se).abs < profile.crit
      return true
    end
    return false
  end
  
  #* Functionailities
  # * Max Item Rule
  #* Parameters 
  # * N/A
  #* Return
  # * [result] : Returns true if satisfy Max Item Rule
  #* Note
  # * N/A
  def maximum_criterion
    num_items = profile.exam.number_of_items
	  case profile.classfication
      when 1
        #Vocabulary(1) : 50 / 3 => 16  
        return num_items > 16
      when 2
        #Grammer(2) : 50 / 3 => 16
        return num_items > 16
      when 3
        #Listening(3) : 60 / 3 => 20
        return num_items > 20
      when 4
        #Reading(4) : 40 / 3 => 13
        return num_items > 13
    end
    return true
  end
end